using System.Collections.Generic;
using ChiWalker.Utilities;
using Styx;
using Styx.CommonBot;
using Styx.TreeSharp;
using Styx.WoWInternals;
using LocationRetriever = ChiWalker.Helpers.LocationRetriever;

namespace ChiWalker.Spell
{
    public class CastAtLocation : Composite
    {
        private WoWSpell _spell;

        public CastAtLocation(int spellId, LocationRetriever location,
            SimpleBooleanDelegate condition = null, ActionSucceedDelegate succeedRunner = null,
            bool doubleCastPrevention = false)
        {
            SpellId = spellId;
            Location = location;
            Condition = condition;
            SucceedRunner = succeedRunner;
            DoubleCastPrevention = doubleCastPrevention;
        }

        public int SpellId { get; set; }

        public WoWSpell Spell
        {
            get { return _spell ?? (_spell = WoWSpell.FromId(SpellId)); }
        }

        public string LogReason { get; set; }
        public LocationRetriever Location { get; set; }
        public SimpleBooleanDelegate Condition { get; set; }
        public ActionSucceedDelegate SucceedRunner { get; set; }
        public bool DoubleCastPrevention { get; set; }

        public override RunStatus Tick(object context)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (!WaitFor.SpellGcd.IsFinished)
                    return RunStatus.Success;

                if (DoubleCastPrevention && WaitFor.LastCastSpell == SpellId)
                    return RunStatus.Failure;

                if (!SpellManager.HasSpell(SpellId))
                    return RunStatus.Failure;

                if (!SpellManager.CanCast(SpellId))
                    return RunStatus.Failure;

                if (Spell.MaxRange <= StyxWoW.Me.Location.Distance(Location(context)))
                    return RunStatus.Failure;

                if (Condition != null && !Condition(context))
                    return RunStatus.Failure;


                Logger.Write("Casting {0} at Location", Spell.Name);
                SpellManager.Cast(SpellId);
                WaitFor.LastCastSpell = SpellId;
                StyxWoW.SleepForLagDuration();
                SpellManager.ClickRemoteLocation(Location(context));
                WaitFor.SpellGcd.Reset();

                if (SucceedRunner != null)
                    SucceedRunner(context);

                return RunStatus.Success;
            }
        }

        protected override IEnumerable<RunStatus> Execute(object context)
        {
            yield return Tick(context);
        }
    }
}